package com.easylinkin.sm.controller;

import com.easylinkin.sm.constant.LogConstant;
import com.easylinkin.sm.dto.ResetPasswordVo;
import com.easylinkin.sm.entity.Role;
import com.easylinkin.sm.entity.User;
import com.easylinkin.sm.service.UserService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import site.morn.boot.data.DisplayableControllerSupport;
import site.morn.core.CriteriaMap;
import site.morn.log.OperateAction;
import site.morn.log.OperateAction.Actions;
import site.morn.log.OperateArguments;
import site.morn.log.OperateGroup;
import site.morn.rest.RestBuilders;
import site.morn.rest.RestMessage;
import site.morn.rest.RestModel;
import site.morn.validate.group.Add;
import site.morn.validate.group.Put;
import site.morn.validate.group.Update;

/**
 * 用户控制器
 *
 * @author timely-rain
 * @since 1.0.0, 2017/9/28
 */
@Api(tags = "用户管理")
@OperateGroup(value = "user", args = LogConstant.Module.USER)
@RestController
@RequestMapping("/user")
public class UserController extends DisplayableControllerSupport<User, Long, UserService> {

  /**
   * 新增
   */
  @ApiOperation("新增")
  @OperateAction(Actions.ADD)
  @PostMapping
  @Override
  public RestMessage add(@Validated(Add.class) @RequestBody RestModel<User> restModel) {
    fillRoles(restModel);
    return super.add(restModel);
  }

  /**
   * 修改个人信息
   */
  @ApiOperation("修改个人信息")
  @OperateAction("profile")
  @PutMapping("profile")
  public RestMessage profile(@Validated(Update.class) @RequestBody RestModel<User> restModel) {
    service().updateProfile(restModel.getModel());
    return RestBuilders.successMessage();
  }

  /**
   * 修改
   */
  @ApiOperation("修改")
  @OperateAction(Actions.UPDATE)
  @PutMapping
  @Override
  public RestMessage update(
      @Validated({Update.class, Put.class}) @RequestBody RestModel<User> restModel) {
    fillRoles(restModel);
    return super.update(restModel);
  }

  /**
   * 锁定
   *
   * @return REST消息
   */
  @ApiOperation("锁定")
  @ApiImplicitParam(name = "ids", value = "用户编号集合", required = true)
  @OperateAction("lock")
  @PutMapping("lock")
  public RestMessage lock(@RequestBody List<Long> ids) {
    OperateArguments.add(ids);
    service().lockAll(ids);
    return RestBuilders.successMessage();
  }

  /**
   * 解锁
   *
   * @return REST消息
   */
  @ApiOperation("解锁")
  @ApiImplicitParam(name = "ids", value = "用户编号集合", required = true)
  @OperateAction("unlock")
  @PutMapping("unlock")
  public RestMessage unlock(@RequestBody List<Long> ids) {
    OperateArguments.add(ids);
    service().unlockAll(ids);
    return RestBuilders.successMessage();
  }

  /**
   * 修改密码
   *
   * @param restModel REST模型
   * @return REST消息
   */
  @ApiOperation("修改密码")
  @OperateAction("password")
  @PutMapping("password")
  public RestMessage password(@Validated @RequestBody RestModel<ResetPasswordVo> restModel) {
    service().updatePassword(restModel.getModel());
    return RestBuilders.successMessage();
  }

  /**
   * 重置密码
   *
   * @param restModel REST模型
   * @return REST消息
   */
  @ApiOperation("重置密码")
  @OperateAction("reset")
  @PutMapping("reset")
  public RestMessage reset(@Validated @RequestBody RestModel<ResetPasswordVo> restModel) {
    service().resetPassword(restModel.getModel());
    return RestBuilders.successMessage();
  }

  /**
   * 按前端模型填充角色
   */
  private void fillRoles(RestModel<User> restModel) {
    User model = restModel.getModel();
    CriteriaMap attach = restModel.getAttach();
    List<Integer> roleIds = attach.getExpect(User.Fields.roles);
    if (CollectionUtils.isEmpty(model.getRoles()) && !CollectionUtils.isEmpty(roleIds)) {
      List<Role> roles = roleIds.stream().map(String::valueOf).map(Long::valueOf).map(i -> {
        Role role = new Role();
        role.setId(i);
        return role;
      }).collect(Collectors.toList());
      model.setRoles(roles);
    }
  }

  /**
   * 生成图片验证码（缓存）
   *
   * @return 图片验证码
   */
  @ApiOperation("忘记密码-生成图片验证码")
  @PostMapping("/verificationCode")
  public RestMessage generateImageVerificationCode() {
    return RestBuilders.successMessage(service().getImage());
  }

  /**
   * 生成验证码并发送到手机（缓存），生成验证码前先对表单校验
   *
   * @return 成功失败消息
   */
  @ApiOperation("忘记密码-生成短信验证码并发送")
  @PostMapping("/sendVerificationCode")
  public RestMessage sendVerificationCode(@RequestBody RestModel<User> restModel) {
    service()
        .sendVerificationCode(restModel.getModel().getUsername(), restModel.getModel().getPhone(),
            restModel.getAttach().get("imageVode").toString());
    return RestBuilders.successMessage();
  }

  /**
   * 表单验证，图片验证码、用户名、手机号、验证码是否正确
   *
   * @return 成功失败消息
   */
  @ApiOperation("忘记密码-表单验证")
  @PostMapping("/verificationMessages")
  public RestMessage verificationMessages(@RequestBody RestModel<User> restModel) {
    return RestBuilders
        .successMessage(service().verificationMessages(restModel.getModel().getUsername(),
            restModel.getModel().getPhone(),
            restModel.getAttach().getString("imageVode"),
            restModel.getAttach().get("code").toString()));
  }

  /**
   * 修改用户密码，若与旧密码重复，则返回提示
   *
   * @return 成功失败消息
   */
  @ApiOperation("忘记密码-修改用户密码")
  @PutMapping("/resetPassword")
  public RestMessage resetPassword(@RequestBody RestModel<User> restModel) {
    service().forgetPassword(restModel.getModel().getUsername(),
        restModel.getModel().getPassword());
    return RestBuilders.successMessage();
  }
}
